﻿/****************************************************************
*   作者：Morain
*   创建时间：2018/2/19 19:31:20
*   描述说明：
*****************************************************************/
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;

namespace ETSModel
{
  /// <summary>
  /// TCP服务
  /// </summary>
  public class TService : AService
  {
    /// <summary>
    /// Tcp监听
    /// </summary>
    private TcpListener acceptor;

    /// <summary>
    /// 对应的连接通道
    /// </summary>
    private readonly Dictionary<long, TChannel> idChannels = new Dictionary<long, TChannel>();

    public TService()
    {

    }

    /// <summary>
    /// 可做Server也可用作Client
    /// </summary>
    /// <param name="iPEndPoint"></param>
    public TService(IPEndPoint iPEndPoint)
    {
      this.acceptor = new TcpListener(iPEndPoint);
      this.acceptor.Server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
      this.acceptor.Server.NoDelay = true;
      this.acceptor.Start();
    }

    /// <summary>
    /// 
    /// </summary>
    /// <returns></returns>
    public override async Task<AChannel> AcceptChannel()
    {
      if (this.acceptor == null) throw new Exception("service construct must use host and port param"); ;
      TcpClient tcpClient = await this.acceptor.AcceptTcpClientAsync();
      TChannel channel = new TChannel(tcpClient, this);
      this.idChannels[channel.Id] = channel;
      return channel;
    }

    public override AChannel ConnectChannel(IPEndPoint iPEndPoint)
    {
      TcpClient tcpClient = new TcpClient();
      TChannel channel = new TChannel(tcpClient, iPEndPoint, this);
      this.idChannels[channel.Id] = channel;
      return channel;
    }

    /// <summary>
    /// 释放资源
    /// </summary>
    public override void Dispose()
    {
      if (this.acceptor == null) return;

      foreach (var id in idChannels.Keys)
      {
        AChannel aChannel = this.idChannels[id];
        aChannel.Dispose();
      }
      this.acceptor.Stop();
      this.acceptor = null;
    }

    /// <summary>
    /// 获取一个通道
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    public override AChannel GetChannel(long id)
    {
      TChannel aChannel = null;
      this.idChannels.TryGetValue(id, out aChannel);
      return aChannel;
    }

    /// <summary>
    /// 根据Id移除
    /// </summary>
    /// <param name="channelId"></param>
    public override void Remove(long channelId)
    {
      TChannel channel = null;
      if (!this.idChannels.TryGetValue(channelId, out channel))
      {
        return;
      }

      this.idChannels.Remove(channelId);
      channel.Dispose();
    }
  }
}
